#include "hackRain.h"

#include <QDesktopWidget>
#include <QPainter>
#include <QPen>
#include <QBrush>
#include <QDebug>
// 嵌入式qt5.7中没有找到这个类
//#include <QRandomGenerator>
#include <QTimer>
#include <QIcon>

int rnd(int beg, int end)
{   // 返回 [beg,end)内的一个int值
    int ret;
    ret = (rand() % (end-beg+1))+ beg;
    return ret;
    //return QRandomGenerator::global()->bounded(beg, end);
}


hackRain::hackRain(QWidget *parent)
    : QWidget(parent)
{
    ui.setupUi(this);

    // 无边框窗口, 黑色背景
    this->setWindowFlags(Qt::FramelessWindowHint);
    this->setStyleSheet("background-color:black;");

    // 使画布全屏
    m_Screen = QDesktopWidget().screenGeometry();   // 获取桌面 QRect(0,0 2560x1440)
    this->resize(m_Screen.width(), m_Screen.height());  // 令窗口大小和桌面大小一样

    // 构建m_rains
    initRain();

    m_painter = new QPainter(this);
    m_painter->setFont(QFont("Times", CharH));

    QTimer* timer = new QTimer(this);
    timer->start(50); // 每隔50ms发送信号
    connect(timer, &QTimer::timeout, [=]() {
        QWidget::update();  // 重绘画面,调用paintEvent()
    });
}

void hackRain::initRain()
{
    for (int i = 0; i < RainNum; i++) {
        m_rains[i].x = rnd(0, m_Screen.width());
        m_rains[i].y = rnd(0, m_Screen.height());
        for (int j = 0; j < StrNum; j++) {
            int type = rnd(0, 3);   // 0数字,1小写字母,2大写字母
            char ch;
            if (type == 0)
                ch = rnd('0', '9' + 1);
            else if (type == 1)
                ch = rnd('a', 'z' + 1);
            else
                ch = rnd('A', 'Z' + 1);
            m_rains[i].str.append(ch);
        }
    }
    status = 0;
    dialog_str.clear();
    dialog1_index = 0;
    delay_cnt = 0;
}

QString hackRain::enter_flash(int cnt,QString str1,QString str2)
{
    int cnt2;
    cnt2 = cnt / 10;
    if(0 == (cnt2 % 2))
    {
        return " ";
    }
    else
    {
        return "■";
    }
}
void hackRain::paintEvent(QPaintEvent* event)
{
    QPen penGreen(QColor(0, 255, 0));
    QString str;

    m_painter->begin(this);
    m_painter->setPen(penGreen);
    switch (status) {
    // flash Enter1
    case 0:
        str = enter_flash(delay_cnt++," ","■");
        if(delay_cnt >= 50)
        {
            delay_cnt = 0;
            status = 1;
        }
        m_painter->drawText(0, 15, str);
        break;
    // show "Weak up, Neo..."
    case 1:
        if(dialog1_index < 15)
        {
            dialog_str.append(dialog_str1.at(dialog1_index++));
            m_painter->drawText(0, 15, dialog_str);
            m_painter->drawText((int)(dialog1_index*8.5), 15, "■");
        }
        else
        {
            m_painter->drawText(0, 15, dialog_str1);
            status = 2;
            dialog_str.clear();
        }
        break;
    // flash Enter2
    case 2:
        str = enter_flash(delay_cnt++," ","■");
        if(delay_cnt >= 50)
        {
            status = 3;
        }
        m_painter->drawText(0, 15, dialog_str1);
        m_painter->drawText((int)(dialog1_index*8.5), 15, str);
        break;
    // show "The Matrix has you"
    case 3:
        if(dialog2_index < 18)
        {
            dialog_str.append(dialog_str2.at(dialog2_index++));
            //m_painter->drawText(0, 15, dialog_str1);
            m_painter->drawText(0, 15, dialog_str);
            m_painter->drawText((int)(dialog2_index*8.5), 15, "■");
        }
        else
        {
            m_painter->drawText(0, 15, dialog_str2);
            status = 4;
            delay_cnt = 0;
        }
        break;
    // flash Enter3
    case 4:
            if(delay_cnt < 40)
            {
                str = enter_flash(delay_cnt++," ","■");
            }
            else if(delay_cnt < 60)
            {
                delay_cnt++;
                str = " ";
            }
            else
            {
                str = " ";
                status = 5;
            }
            //m_painter->drawText(0, 15, dialog_str1);
            m_painter->drawText(0, 15, dialog_str2);
            m_painter->drawText((int)(dialog2_index*8.5), 15, str);
            break;
    }
    if(status < 5)
    {
        m_painter->end();
        return;
    }

    for (int i = 0; i < RainNum; i++) {
        m_rains[i].y += CharH * rnd(1, 3);   // 降落1~2个字符
        // 若雨滴已经完全落下, 则让它从上面重新复活
        if (m_rains[i].y >= m_Screen.height() + StrNum * CharH) {
            m_rains[i].x = rnd(0, m_Screen.width());
            m_rains[i].y = 0;
        }
        for (int j = 0; j < StrNum; j++) {
            //QPen penGreen(QColor(0, 255 - 40 * j, 0));    // 颜色渐浅
            penGreen.setColor(QColor(0, 255 - 40 * j, 0));
            m_painter->setPen(penGreen);
            int x = m_rains[i].x;
            int y = m_rains[i].y - j * CharH;
            m_painter->drawText(x, y, m_rains[i].str.at(j));
        }
    }

    m_painter->end();
}

void hackRain::mouseMoveEvent(QMouseEvent* event)
{
    qApp->quit();   // 移动后退出
}
